package com.york.jobmew.circle.server.util;

import com.york.jobmew.circle.api.common.TreeNode;
import org.springframework.util.CollectionUtils;

import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 树形结构工具类，用于构建和操作树形数据结构，适用于评论树、菜单树等场景
 */
public class TreeUtils {

    /**
     * 根据节点列表构建树形结构
     *
     * @param nodes 节点列表，每个节点需实现TreeNode接口
     * @param <T>   节点类型，需继承TreeNode
     * @return 构建完成的树形结构列表（根节点列表）
     */
    public static <T extends TreeNode> List<T> buildTree(List<T> nodes) {
        // 如果节点列表为空，返回空列表
        if (CollectionUtils.isEmpty(nodes)) {
            return Collections.emptyList();
        }

        // 按父节点ID分组，生成Map<父节点ID, 子节点列表>
        Map<Long, List<TreeNode>> groups = nodes.stream()
                .collect(Collectors.groupingBy(TreeNode::getNodePId));

        // 构建树形结构：
        // 1. 过滤非空节点
        // 2. 为每个节点设置其子节点
        // 3. 过滤出根节点（根节点的父节点ID通常为0或null）
        return nodes.stream()
                .filter(Objects::nonNull)
                .peek(node -> {
                    List<TreeNode> children = groups.get(node.getNodeId());
                    node.setChildren(children);
                })
                .filter(TreeNode::getRootNode)
                .collect(Collectors.toList());
    }

    /**
     * 查找树中与目标ID匹配的节点及其所有子节点
     *
     * @param result   存放匹配结果的列表
     * @param node     当前遍历的节点
     * @param targetId 目标节点ID
     * @param <T>      节点类型，需继承TreeNode
     */
    public static <T extends TreeNode> void findAll(List<T> result, TreeNode node, Long targetId) {
        // 如果当前节点的ID或父节点ID与目标ID匹配，则将当前节点及其子节点加入结果列表
        if (node.getNodeId().equals(targetId) || node.getNodePId().equals(targetId)) {
            addAll(result, node);
        } else {
            // 递归遍历子节点
            if (!CollectionUtils.isEmpty(node.getChildren())) {
                for (TreeNode child : node.getChildren()) {
                    findAll(result, child, targetId);
                }
            }
        }
    }

    /**
     * 将当前节点及其所有子节点加入结果列表
     *
     * @param result 存放匹配结果的列表
     * @param node   当前节点
     * @param <T>    节点类型，需继承TreeNode
     */
    private static <T extends TreeNode> void addAll(List<T> result, TreeNode node) {
        result.add((T) node);
        // 递归添加子节点
        if (!CollectionUtils.isEmpty(node.getChildren())) {
            for (TreeNode child : node.getChildren()) {
                addAll(result, child);
            }
        }
    }
}